package com.hhkj.study.common.service;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hhkj.study.admin.config.entity.ConfigBase;
import com.hhkj.study.admin.config.service.extend.ConfigBaseExtendService;
import com.hhkj.study.admin.user.entity.UserWechatCompany;
import com.hhkj.study.admin.user.service.base.UserWechatCompanyService;
import com.hhkj.study.api.user.common.handler.AccountSessionHandler;
import com.hhkj.study.api.user.model.res.ApiCustomerUserBaseRes;
import com.hhkj.study.common.handler.AliyunOssUploader;
import com.hhkj.study.common.model.req.UserWechatReq;
import com.hhkj.study.common.model.req.WechatQrState;
import com.hhkj.study.common.model.res.AliyunOssRes;
import com.hhkj.study.common.model.res.UserWechatRes;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.cont.SysConst;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.DictCodeEnum;
import com.ruoyi.common.enums.QrCodeStatusEnum;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.model.ThirdPartyRes;
import com.ruoyi.common.thirdparty.wecom.WeComApiClient;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.common.utils.wechat.WechatAppUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author luowu
 * @Date 2024/9/12 涵 9:41:56
 */
@Slf4j
@Service
public class CommonService {

    @Resource
    private AliyunOssUploader aliyunOssUploader;

    @Resource
    private RedisCache redisCache;

    @Resource
    private UserWechatCompanyService userWechatCompanyService;

    @Resource
    private ConfigBaseExtendService configBaseExtendService;

    @Resource
    private WeComApiClient weComApiClient;

    /** 生成联系我企业客服二维码过期时间 */
    private static final Integer QW_QR_EXPIRE_DAYS = 1;


    /**
     * 批量上传文件返回源文件及上传的url
     * @param fileList
     * @return
     */
    public List<AliyunOssRes> uploadBatch(List<MultipartFile> fileList) {
        if (fileList.size() <= 0) {
            throw new GlobalException("上传文件为空");
        }
        List<AliyunOssRes> list = new ArrayList<>();
        if (fileList.size() > 1) {
            list = aliyunOssUploader.uploadAndSaveBatch(fileList);
        } else {
            list.add(aliyunOssUploader.uploadFile(CollectionUtil.getFirst(fileList)));
        }
        return list;
    }

    /**
     * 生成小程序码
     * @param scene
     * @return
     */
    public String generateQrCode(String scene) {
        // 生成二维码时将临时唯一标识放入缓存,并且设置默认状态
        String dataUrl = WechatAppUtil.generateDataUrl(scene);
        if (StrUtil.isBlank(dataUrl)) {
            throw new GlobalException("小程序码生成失败,请重试");
        }
        redisCache.setCacheObject(RedisUtils.createKey(Constants.WX_SCAN_KEY_PREFIX, scene), QrCodeStatusEnum.UN_SCAN.getCode(), Constants.TWO_MINUTES, TimeUnit.MINUTES);
        return dataUrl;
    }

    /**
     * 根据微信code获取微信用户凭据unionId
     * @param code
     * @return
     */
    public ThirdPartyRes getThirdPartyCert(String code) {
        WxMaJscode2SessionResult openIdRes = WechatAppUtil.getWxIdRes(code);
        ThirdPartyRes thirdPartyRes = new ThirdPartyRes();
        thirdPartyRes.setThirdPartyId(openIdRes.getUnionid());
        return thirdPartyRes;
    }

    /**
     * 检查用户是否添加微信客服 未添加则返回需要添加的客服二维码
     * @param req
     * @return
     */
    public UserWechatRes checkUserWechat(UserWechatReq req) {
        ApiCustomerUserBaseRes currentAccount = AccountSessionHandler.getCurrentAccount();
        // 配置的客服列表 可能存在一个课程有多个客服,只需添加一个客服就可以
        List<ConfigBase> kfConfigList = configBaseExtendService.getConfigByCourseType(DictCodeEnum.KF_CONFIG.getCode(), req.getCourseType());
        UserWechatRes userWechatRes = new UserWechatRes();
        userWechatRes.setAddWechatFlag(SysConst.Flag.NO.getFlag());
        if (CollectionUtil.isNotEmpty(kfConfigList)) {
            List<String> wxUserIdList = kfConfigList.stream().map(ConfigBase::getExtra).collect(Collectors.toList());
            LambdaQueryWrapper<UserWechatCompany> userWechatCompanyQuery = new LambdaQueryWrapper<>();
            userWechatCompanyQuery.eq(UserWechatCompany::getUserId, currentAccount.getId())
                    .in(UserWechatCompany::getWxOrgId, wxUserIdList);
            long count = userWechatCompanyService.count(userWechatCompanyQuery);
            // 添加了企业微信客服 返回添加了微信标识
            if (count > 0) {
                userWechatRes.setAddWechatFlag(SysConst.Flag.IS.getFlag());
            } else {
                // 随机获得一个企业微信客服
                String userId = CollectionUtil.get(wxUserIdList, new Random().nextInt(wxUserIdList.size()));
                // 配置微信二维码中带有标识的参数 后续通过回调地址中获取到该参数识别该用户
                String qrCodeUrl = getWeComQrUrl(currentAccount.getId(), userId, req.getAddSource());
                userWechatRes.setQrCodeUrl(qrCodeUrl);
            }
            return userWechatRes;
        }
        return userWechatRes;
    }

    /**
     *  通过添加来源 企业微信用户id 获取二维码链接
     * @param userId 业务用户id
     * @param qxUserId 企业用户id
     * @param addSource 添加来源
     * @return
     */
    public String getWeComQrUrl(Long userId, String qxUserId, Long addSource) {
        String qyQrCodeCacheKey = RedisUtils.createKey(Constants.QY_WX_QRCODE_URL_PREFIX, String.valueOf(userId), String.valueOf(addSource));
        Object cacheObject = redisCache.getCacheObject(qyQrCodeCacheKey);
        if (ObjectUtil.isNotNull(cacheObject)) {
            return String.valueOf(cacheObject);
        } else {
            WechatQrState wechatQrState = new WechatQrState(userId, addSource);
            String qrCodeUrl;
            try {
                qrCodeUrl = weComApiClient.generateWeComQrCode(qxUserId, JSONUtil.toJsonStr(wechatQrState));
            } catch (Exception e) {
                log.error("生成企业微信二维码失败", e);
                return null;
            }
            redisCache.setCacheObject(qyQrCodeCacheKey, qrCodeUrl, QW_QR_EXPIRE_DAYS, TimeUnit.DAYS);
            return qrCodeUrl;
        }
    }
}
